﻿#include "DeviceCANHub.h"

using namespace DeviceLayer;

DYNAMIC_CREATE(DeviceCANHub)

DeviceCANHub::DeviceCANHub()
{

}

DeviceCANHub::~DeviceCANHub()
{
    //TODO:
    //如果有can总线的清理工作，需要在这里补充

    //退出线程
    run = false;
    if (canThread.joinable())
        canThread.join();   //确保线程退出。
}

/*
TODO:
    需要补充can总线的初始化代码
*/
bool DeviceCANHub::InitFromSettingData(const QString &path)
{
    //需要从SettingData.xml读入can的配置，并初始化can总线。
    //在这里补充初始化can总线的代码。



    //建立can收发线程并启动
    run = true;
    canThread = std::thread(&DeviceCANHub::canThreadFunc, this);

    return true;
}

//TODO：需要完成此函数
/**
 * @brief can总线收发线程
 * 
 */
void DeviceCANHub::canThreadFunc()
{
    can_frame receivedFrame {0};
    while (run)
    {
        std::unique_lock<std::mutex> lock(mtxQueue);
        //只要队列里还有内容，就发送到总线上。
        while (!msgSendQueue.empty())
        {
            CANMsgQueueInfo msgInfo = msgSendQueue.front();
            //TODO
            //这里需要加入具体发送数据帧的代码

            //TODO
            //如果需要马上等待应答，则应该在这里等待，直到接收到id相同的应答
            //要注意超时处理报错。
            while (msgInfo.waitForResponse)
            {
                blockingInfo.blockStatus = BlockStatus::blocking;   //这两个赋值语句的顺序不可更改！
                blockingInfo.deviceBeingBlocked = msgInfo.msg.id;
                //...

                //收到数据帧时，要根据id查找回调函数：
                CANHubCallback callback = callbackMap.at(receivedFrame.id);
                if (callback != nullptr)
                    callback(receivedFrame);    //如果有回调函数，则调用它。

                if (receivedFrame.id == msgInfo.msg.id)
                {
                    //收到应答
                    blockingInfo.blockStatus = BlockStatus::notBlocked;
                    cv.wait(lock);
                    break;
                }
                //if (超时)
                //{
                    blockingInfo.blockStatus = BlockStatus::overtime;
                    cv.wait(lock);
                    break;
                //}
            }

            msgSendQueue.pop();
        }
        lock.unlock();

        //发送一个数据帧之后，无论是不是需要等待应答，在这里都要接收一下can总线上的数据，并且在收到数据帧时，根据id查找回调函数调用。
        while (true)
        {
            //if (接收到数据帧)
            //{
                //收到数据帧时，要根据id查找回调函数：
                CANHubCallback callback = callbackMap.at(receivedFrame.id);
                if (callback != nullptr)
                    callback(receivedFrame);    //如果有回调函数，则调用它。

            //}
            //else
            //  break;
        }

        //此时，待发送队列为空、can总线上没有接收到的数据。在下一次循环之前，等待5毫秒，以便交还CPU给操作系统。
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
    }
}
